'''Written by Dan Kearney, Natalie Mattison, and Theodore Thompson,
for Olin College Computational Modeling 2011'''

from Sugarscape import Sugarscape
import pygame,sys
import matplotlib
from pygame.locals import *
import DataCollect
matplotlib.rc('xtick', labelsize=2) 
matplotlib.rc('ytick', labelsize=2)
from Slider import *
from Button import *
import csv
import matplotlib.backends.backend_agg as agg
import matplotlib.pyplot as pyplot
import time

class Gui:
	def __init__(self,sugarscape, vision_range=3, metabolism_range=3, alpha_range=3, num_agents_range=500, max_sugar_range=5, sugar_growth_range=.5, tax_rate_range=.5):
		pygame.init()
		self.square_length=10
		self.square_width=self.square_length
		self.options_width = 200
		self.buffer = 1
		self.sugarscape = sugarscape
		self.graph_buffer = 5
		self.graph_panel_length = (self.sugarscape.length*(self.square_length + self.buffer))/2
		self.title_fontsize = 4
		self.background_color = (0,0,0)
		self.sliders = []
		self.buttons = []


		self.vision_range = vision_range
		self.metabolism_range = metabolism_range
		self.alpha_range = alpha_range
		self.num_agents_range = num_agents_range
		self.max_sugar_range = max_sugar_range
		self.sugar_growth_range = sugar_growth_range
		self.tax_rate_range = tax_rate_range
		
		self.clicked = {}
		self.started = False
		self.reset = False
		
		self.window=pygame.display.set_mode(((self.square_length+self.buffer)*sugarscape.length + self.graph_panel_length + self.graph_buffer*2,(self.square_width+self.buffer)*sugarscape.width + self.options_width))
		pygame.display.set_caption("Sugarscape")
		self.agent_color = pygame.Color(0,180,0)
		self.event_loop(sugarscape)
	
	def event_loop(self,sugarscape):
		self.initialize_graph()
		self.draw_controls()
		while True:
			if self.started:
				sugarscape.nextstep() 
				self.update_graph(self.sugarscape.timestamp)
			self.draw_sugarscape_info()
			for event in pygame.event.get():
				self.handle_events(event)				
			for i in range(sugarscape.length):
				for j in range(sugarscape.width):
					loc=sugarscape.get_location(i,j)
					health=loc.get_sugar_amt()/float(loc.get_max_sugar())
					healthColor=pygame.Color(50 if loc.is_rich else 0, 0, int(250*health))
					pygame.draw.rect(self.window,healthColor,((self.square_length + self.buffer)*i,(self.square_width + self.buffer)*j,self.square_length,self.square_width))
					if loc.get_has_agent():
						pygame.draw.circle(self.window,self.agent_color,(int((self.square_width+self.buffer)*i)+int((self.square_width + self.buffer)/2.),
																		  int((self.square_length+self.buffer)*j)+int((self.square_length + self.buffer)/2.) ),
																		 int(self.square_length/3.0))
			pygame.display.update()
	
	
	
	def handle_events(self, event):
		'''deals with clicks, unclicks, etc'''
		if event.type==QUIT:
			pygame.quit()
			sys.exit()
		if event.type==MOUSEBUTTONDOWN:
			self.handle_click(*event.pos)
		if event.type==MOUSEMOTION:
			self.handle_slider_motion(*event.pos)
		if event.type==MOUSEBUTTONUP:
			self.release_all_sliders()
			self.release_all_buttons()
		return True
				
	def release_all_buttons(self):
		'''releases all buttons'''
		for button in self.buttons:
			button.unclick_button()
	
	def handle_click(self,x,y):
		'''handles all possible click events'''
		for slider in self.sliders:
			slider.click_slider(x,y)
		for button in self.buttons:
			button.click_button(x,y)
		return False
	
	def handle_slider_motion(self, x, y):
		'''handles slider motion'''
		for slider in self.sliders:
			slider.move_slider(x,y)
		return False
	
	def update_graph(self,timestamp):
		'''this updates the histogram. 
		It alternately clears the axes
		and actually calculating the new histogram and displaying it.'''
		if timestamp % 5 == 0:
			x,y = [],[]
			num_agents = self.sugarscape.num_agents
			wealths = self.sugarscape.agent_wealths()
			self.ax.hist(wealths, 20, normed=False)
			self.canvas.draw()
			renderer = self.canvas.get_renderer()
			raw_data = renderer.tostring_rgb()
			surf = pygame.image.fromstring(raw_data, self.canvas_width_height, "RGB")
			self.screen.blit(surf, ((self.square_length+self.buffer)*self.sugarscape.length + self.graph_buffer,self.graph_buffer))
		else:
			self.ax.cla()
		return True
	
	def initialize_graph(self):
		'''this is a bunch of code to make the histogram graph
		display.  It instantiates the graph and sets some class attributes
		so that update_graph runs a little faster'''
		
		#graph making section
		fig = pyplot.figure(figsize=[1, 1], dpi=self.graph_panel_length)
		self.ax = fig.gca()
		wealths = self.sugarscape.agent_wealths()
		self.ax.hist(wealths, 20, normed=False)
		pyplot.suptitle('Wealth Histogram', fontsize=self.title_fontsize)
		
		#rendering
		self.canvas = agg.FigureCanvasAgg(fig)
		self.canvas.draw()
		renderer = self.canvas.get_renderer()
		raw_data = renderer.tostring_rgb()
		self.screen = pygame.display.get_surface()
		self.canvas_width_height = self.canvas.get_width_height()
		surf = pygame.image.fromstring(raw_data, self.canvas_width_height, "RGB")
		self.screen.blit(surf, ((self.square_length+self.buffer)*self.sugarscape.length + self.graph_buffer,self.graph_buffer))
		return True
	
	
	def draw_controls(self):
		'''draws sliders and buttons'''
		offset = (self.sugarscape.length*(self.square_length + self.buffer))
		coords = [(150,40),(150,120),(275,40),(275,120),(400,40),(400,120)]
		button_coords = [(25, 20), (25, 100)]
		Slider(coords[0][0], offset + coords[0][1], 'metabolism.png', self, self.sugarscape.set_agent_metabolism,self.sugarscape.agent_metabolism, self.metabolism_range, min_val = .1)
		Slider(coords[1][0], offset + coords[1][1], 'vision.png', self, self.sugarscape.set_agent_vision,self.sugarscape.agent_vision, self.vision_range, min_val = 1, is_int = True)
		Slider(coords[2][0], offset + coords[2][1], 'num_agents.png', self, self.sugarscape.set_num_agents,self.sugarscape.num_agents, self.num_agents_range, min_val = 1, is_int = True)
		Slider(coords[3][0], offset + coords[3][1], 'max_sugar.png', self, self.sugarscape.set_max_sugar,self.sugarscape.max_sugar, self.max_sugar_range, min_val = .1)
		Slider(coords[4][0], offset + coords[4][1], 'sugar_growth.png', self, self.sugarscape.set_sugar_growth_rate,self.sugarscape.sugar_growth_rate, self.sugar_growth_range, min_val = .1)
		Slider(coords[5][0], offset + coords[5][1], 'tax_rate.png', self, self.sugarscape.set_tax_rate,self.sugarscape.tax_rate, self.tax_rate_range, is_percent = True)
		Button(button_coords[0][0], button_coords[0][1] + offset, self, 'start.png', 'start_depressed.png', func = self.pause)
		Button(button_coords[1][0], button_coords[1][1] + offset, self, 'reset.png', 'reset_depressed.png', func = self.sugarscape.reset, stay_depressed = False)

	def release_all_sliders(self):
		'''set all sliders to not grabbed'''
		for slider in self.sliders:
			slider.unclick_slider()

	def pause(self):
		'''pauses the sugarscape'''
		self.started = not self.started
	
	def draw_sugarscape_info(self):
		'''draws the text about the sugarscape'''
		if self.sugarscape.timestamp % 10 != 0:
			return
		data = DataCollect.DataCollect(self.sugarscape).Pack()
		value_dict = { "Standard deviation: " : round(data[1],1),
					"Mean wealth: " : round(data[2],1),
					"Median wealth: " : round(data[3],1),
					"Total wealth: " : round(data[7],1),
					"Number of agents: ": len(self.sugarscape.agents),
					"Gini coefficient: " : round(data[8],2),
					"Timestep: " : self.sugarscape.timestamp,
					"Bottom quartile: " : round(data[9],2)
					}
		scape_width = ((self.square_length+self.buffer)*self.sugarscape.length + self.graph_buffer) + 10
		for (i, key) in enumerate(value_dict.keys()):
			self.write_text(scape_width, scape_width/2 + 30*i + 10, key + str(value_dict[key]))
		return True
		
		
	def write_text(self, x, y, text):
		'''writes text on the sugarscape. 
		puts a big black box behind to ensure erasure of the last message'''
		msg_object = pygame.font.Font('freesansbold.ttf', 18).render(text, False, (255,255,255))
		msg_rect = msg_object.get_rect()
		msg_rect.topleft = (x, y)
		pygame.draw.rect(self.window, self.background_color, (0, y, 100000, msg_rect.height))
		self.window.blit(msg_object, msg_rect)
		
		
	
if __name__=='__main__':
	a = Sugarscape()
	l=Gui(a)
	#test code
	
	
